package com.genius.reservation.receiver.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.genius.reservation.car.entity.ReservationStartCarInformation;
import com.genius.reservation.common.ResponseRule;
import com.genius.reservation.common.constant.Constant;
import com.genius.reservation.common.constant.ResStatusCode;
import com.genius.reservation.common.rabbitmq.RabbitMessageEntity;
import com.genius.reservation.common.rabbitmq.RabbitService;
import com.genius.reservation.evaluate.entity.EvaluateInformation;
import com.genius.reservation.inspect.entity.InspectName;
import com.genius.reservation.inspect.entity.InspectRecord;
import com.genius.reservation.inspect.entity.InspectType;
import com.genius.reservation.inspect.entity.ReservationToInspect;
import com.genius.reservation.mapper.*;
import com.genius.reservation.platform.entity.PlatformInformation;
import com.genius.reservation.platform.service.IPlatformService;
import com.genius.reservation.receiveRecord.entity.ReceiveRecordInformation;
import com.genius.reservation.receiveRecord.service.IReceiveRecordInformationService;
import com.genius.reservation.receiver.entity.ReceiveStatistics;
import com.genius.reservation.receiver.entity.ReceiverInformation;
import com.genius.reservation.receiver.service.IReceiverInformationService;
import com.genius.reservation.reservation.entity.ReservationInformation;
import com.genius.reservation.reservation.service.IReservationInformationService;
import com.genius.reservation.tools.SendWXMsg;
import com.genius.reservation.user.entity.UserInformation;
import com.genius.reservation.user.service.IUserInformationService;
import org.apache.poi.ss.formula.functions.Now;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.rmi.server.ExportException;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author baomidou
 * @since 2022-05-26
 */
@Service
public class ReceiverInformationServiceImpl extends ServiceImpl<ReceiverInformationMapper, ReceiverInformation> implements IReceiverInformationService {

    @Autowired
    IReservationInformationService reservationService;

    @Autowired
    RabbitService rabbitService;

    @Autowired
    IReceiveRecordInformationService receRecoService;

    @Autowired
    @Lazy
    IUserInformationService userService;

    @Autowired
    SendWXMsg sendWXMsg;

    @Autowired
    @Lazy
    IPlatformService platformService;

    @Autowired
    @Lazy
    ReservationToInspectMapper rtiService;

    @Autowired
    @Lazy
    InspectTypeMapper inspectTypeMapper;

    @Autowired
    @Lazy
    InspectNameMapper inspectNameMapper;

    @Autowired
    @Lazy
    InspectRecordMapper inspectRecordMapper;

    @Autowired
    @Lazy
    ReservationStartCarInformationMapper reservationStartCarMapper;

    @Autowired
    @Lazy
    ReservationStartCarInformationMapper startCarMapper;

    @Autowired
    @Lazy
    EvaluateInformationMapper evaluateMapper;

    @Autowired
    @Lazy
    ReceiveRecordInformationMapper receiverRecordMapper;



//    public static Map<String, RabbitMessageEntity> message = new HashMap<>();

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ReceiverInformation createReceiver(UserInformation user) {
        ReceiverInformation receiverByReceiverNumber = this.getReceiverByReceiverNumber(user.getUserNumber());
        if (ObjectUtil.isEmpty(receiverByReceiverNumber)) {
            ReceiverInformation receiverInformation = new ReceiverInformation();
            receiverInformation.setReceiverNumber(user.getUserNumber());
            receiverInformation.setReceiverName(user.getName());
            receiverInformation.setDutyFlag(0);
            receiverInformation.setIsFree(1);
            return this.addAndUp(receiverInformation);
        }else {
            return receiverByReceiverNumber;
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseRule startReceive(String reservationNumber, String carCode, String receiverNumber) {
        synchronized (this) {
            ReservationInformation re = reservationService.getByReservationNumber(reservationNumber);
            LambdaQueryWrapper<ReservationStartCarInformation> eq = reservationStartCarMapper.getWrapper().eq(ReservationStartCarInformation::getCarCode, carCode).
                    eq(ReservationStartCarInformation::getReservationNumber, reservationNumber).
                    eq(ReservationStartCarInformation::getNowStatus, ResStatusCode.RESERVATION_ARRIVE);
            ReservationStartCarInformation rc = reservationStartCarMapper.selectOne(eq);
            if (ObjectUtil.isEmpty(rc)) {
                return ResponseRule.no("未找到车辆信息");
            }
            if (rc.getNowStatus() != ResStatusCode.RESERVATION_ARRIVE || rc.getNowStatus() == ResStatusCode.START_RECEIVE)
                return ResponseRule.no("操作失败,状态异常");

            if (!Objects.equals(rc.getActualReceiverNumber(), receiverNumber)) {
                return ResponseRule.no("收货员信息不符,请联系收货主管");
            } else {
                rc.setNowStatus(ResStatusCode.START_RECEIVE);
                EvaluateInformation evaluateInformation = new EvaluateInformation();
                evaluateInformation.setEvaluateNumber(Constant.EVALUATE_PREFIX + DateTime.now().toString().replace("-", "").replace(":", "").replace(" ", ""));
                evaluateInformation.setReceiverNumber(receiverNumber);
                EvaluateInformation evaluateInformation1 = evaluateMapper.ad(evaluateInformation);
                ReceiveRecordInformation receiveRecordInformation = new ReceiveRecordInformation();
                receiveRecordInformation.setReceiveRecordNumber(Constant.RECEIVE_RECORD_PREFIX + DateTime.now().toString().replace("-", "").replace(":", "").replace(" ", ""));
                receiveRecordInformation.setReceiverNumber(receiverNumber);
                receiveRecordInformation.setReservationNumber(reservationNumber);
                receiveRecordInformation.setReceiveStartTime(DateTime.now().toString());
                receiveRecordInformation.setReceiveStatus(1);//正在进行
                receiveRecordInformation.setEvaluateNumber(evaluateInformation1.getEvaluateNumber());
                receiveRecordInformation.setSupplierName(re.getSupplierName());
                ReceiveRecordInformation receiveRecordInformation1 = receiverRecordMapper.ad(receiveRecordInformation);
                rc.setReceiveRecordNumber(receiveRecordInformation1.getReceiveRecordNumber());
                rc.setActualReceiverNumber(receiverNumber);
                rc.setNowStatus(ResStatusCode.START_RECEIVE);
                //修改收货员的空闲状态
                ReceiverInformation receiverByReceiverNumber = this.getReceiverByReceiverNumber(receiverNumber);
                if(receiverByReceiverNumber.getIsFree()==0||receiverByReceiverNumber.getDutyFlag()!=0){
                    return ResponseRule.no("收货员忙碌中");
                }
                receiverByReceiverNumber.setIsFree(0);


                //修改月台空闲状态
                PlatformInformation platformById = platformService.findPlatformById(rc.getActualPlatformNumber());
                if(platformById.getPlatformIsUse()==1){
                    return ResponseRule.no("月台占用中");
                }
                platformById.setPlatformIsUse(1);
                //循环吧所有的车都开始收货


                ReservationStartCarInformation reservationStartCarInformation = reservationStartCarMapper.up(rc);//发车记录
                ReceiverInformation receiverInformation = this.addAndUp(receiverByReceiverNumber);//收货员状态
                PlatformInformation platformInformation = platformService.addAndUp(platformById);//月台记录

                //二维码改变
                re.setQRCode(null);

                ReservationInformation reservationInformation = reservationService.addAndUp(re);//预约记录

                boolean flag = true;
                for (ReservationStartCarInformation driver : re.getDrivers()) {
                    if (driver.getNowStatus() != ResStatusCode.START_RECEIVE) {
                        flag = false;
                        break;
                    }
                }

                RabbitMessageEntity<Object> o = new RabbitMessageEntity<>();
                o.setMsg("收货员已开始收货");
                o.setReservationNumber(receiverNumber);
                o.setData(reservationInformation);
                rabbitService.ToReceiverManager(o);
                rabbitService.ToDriver(o);
                sendWXMsg.sendMsg(rc.getDriverWxNumber(), "开始收货");
                if (flag) {
                    //二维码改变
                    re.setQRCode(null);
                    re.setNowStatus(ResStatusCode.START_RECEIVE);
                    reservationInformation = reservationService.addAndUp(re);//预约记录
                    return ResponseRule.ok(reservationStartCarInformation, "所有车辆均已开始收货");
                } else {
                    return ResponseRule.ok(reservationStartCarInformation, "开始收货");
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = ExportException.class)
    public ResponseRule finishReceive(String reservationNumber, String receiverNumber, String receiveRecordNumber) {
        synchronized (this) {
            ReservationInformation re = reservationService.getByReservationNumber(reservationNumber);
            LambdaQueryWrapper<ReservationStartCarInformation> eq = reservationStartCarMapper.getWrapper().eq(ReservationStartCarInformation::getReceiveRecordNumber, receiveRecordNumber);
            ReservationStartCarInformation rc = reservationStartCarMapper.selectOne(eq);
            if (rc.getNowStatus() != ResStatusCode.START_RECEIVE || rc.getNowStatus() == ResStatusCode.FINISH_RECEIVE)
                return ResponseRule.no("操作失败,状态异常");
            LambdaQueryWrapper<ReceiveRecordInformation> eq1 = receiverRecordMapper.getWrapper().eq(ReceiveRecordInformation::getReceiveRecordNumber, receiveRecordNumber);
            ReceiveRecordInformation receiveRecordInformation = receiverRecordMapper.selectOne(eq1);
            receiveRecordInformation.setReceiveStatus(0);
            receiveRecordInformation.setFinishTime(DateTime.now().toString());
            receiveRecordInformation.setUseTime(String.valueOf(DateUtil.between(DateUtil.parse(receiveRecordInformation.getReceiveStartTime()), DateUtil.parse(receiveRecordInformation.getFinishTime()), DateUnit.MINUTE)));
            ReceiveRecordInformation receiveRecord = receRecoService.addAndUp(receiveRecordInformation);
            rc.setNowStatus(ResStatusCode.RESERVATION_FINISH);
            ReservationStartCarInformation up = reservationStartCarMapper.up(rc);


            // 修改收货员的空闲状态
            ReceiverInformation receiverInformation = this.getReceiverByReceiverNumber(up.getActualReceiverNumber());
            if(receiverInformation.getIsFree()!=1) receiverInformation.setIsFree(1);
            this.getBaseMapper().update(receiverInformation);

            //修改月台空闲状态
            PlatformInformation platformById = platformService.findPlatformById(up.getActualPlatformNumber());
            if(platformById.getPlatformIsUse()!=0) platformById.setPlatformIsUse(0);
            platformService.addAndUp(platformById);


            HashMap<String, Object> obj = new HashMap<>();
            ReservationInformation reservationInformation = reservationService.addAndUp(re);
            obj.put("receiveRecord", receiveRecord);
            obj.put("startCar", up);
            RabbitMessageEntity<Object> o = new RabbitMessageEntity<>();
            o.setMsg("收货已完成,等待评价");
            o.setReservationNumber(reservationNumber);
            //开始写收货员的微信通知消息  广发
            String supplierWxNumber = userService.getUserByUserNumber(re.getSupplierNumber()).getWxNumber();
            sendWXMsg.sendMsg(up.getDriverWxNumber(),  "收货已完成请扫码完成评价");
            sendWXMsg.sendMsg(supplierWxNumber, "单号:"+re.getReservationNumber()+",收货已完成");
            boolean flag = true;
            ReservationInformation rrr = reservationService.getByReservationNumber(reservationNumber);
            for (ReservationStartCarInformation driver : rrr.getDrivers()) {
                if (driver.getNowStatus() != ResStatusCode.FINISH_RECEIVE) {
                    flag = false;
                    break;
                }
            }
            o.setData(reservationInformation);
            if (flag) {
                re.setNowStatus(ResStatusCode.RESERVATION_FINISH);
                reservationInformation = reservationService.addAndUp(re);
                obj.put("reservation", reservationInformation);
                rabbitService.ToDriver(o);
                rabbitService.ToReceiverManager(o);
                return ResponseRule.ok(obj, "预约单均已装卸完成");
            } else {
                rabbitService.ToDriver(o);
                rabbitService.ToReceiverManager(o);
                obj.put("reservation", reservationInformation);
                return ResponseRule.ok(obj, "预约单已完成");
            }
        }
    }

//    @Override
//    @Transactional(rollbackFor = ExportException.class)
//    public ResponseRule confirmReservation(String receiverNumber, String reservationNumber) {
//        ReservationInformation reser = reservationService.getByReservationNumber(reservationNumber);
//        reser.setNowStatus(ResStatusCode.RESERVATION_CONFIRM);
//        RabbitMessageEntity<Object> o = new RabbitMessageEntity<>();
//        ReservationInformation reservationInformation = reservationService.addAndUp(reser);
//        o.setData(reservationInformation);
//        o.setMsg("收货员已确认,预约单可以发车");
//        o.setReservationNumber(reservationNumber);
//        rabbitService.ToReceiverManager(o);
//        rabbitService.ToDriver(o);
//        return ResponseRule.ok("预约单已确认");
//    }

    @Override
    public ReceiverInformation getReceiverByReceiverNumber(String receiverNumber) {
        return this.getBaseMapper().selectReceiverNumber(receiverNumber);
    }

    @Override
    public ResponseRule getStatistical(String receiverNumber) {

        HashMap<String, Object> result = new HashMap<>();
        String s = DateTime.now().toString("yyyy-MM");

        //当天这个收货员的订单记录
        LambdaQueryWrapper<ReservationStartCarInformation> like1 = reservationStartCarMapper.getQueryWrapper().eq(ReservationStartCarInformation::getActualReceiverNumber, receiverNumber).like(ReservationStartCarInformation::getActualArrivalTime, s);
        List<ReservationStartCarInformation> reservationStartCarInformations = reservationStartCarMapper.selectList(like1);

        //如果没找到记录就报错
        if (ObjectUtil.isEmpty(reservationStartCarInformations)){
            return ResponseRule.no("没有找到车辆记录");
        }

        //给到订单记录数
        result.put("orderCount",reservationStartCarInformations.size());

        //获取所有的供应商名字
        ArrayList<String> list = new ArrayList<>();
        for (ReservationStartCarInformation reservationStartCarInformation : reservationStartCarInformations) {
            list.add(reservationStartCarInformation.getSupplierName());
        }
        //去重
        HashSet<String> objects = new HashSet<>(list);
        objects.addAll(list);

        //供应商总数
        result.put("supplierCount",objects.size());

        //根据收货员编号和完成时间搜索已收货完成的单子
        LambdaQueryWrapper<ReceiveRecordInformation> like = receiverRecordMapper.getQueryWrapper().eq(ReceiveRecordInformation::getReceiverNumber, receiverNumber).like(ReceiveRecordInformation::getFinishTime, s);
        List<ReceiveRecordInformation> receiveRecordInformations = receiverRecordMapper.selectList(like);

        //如果为空就没有完成的记录
        if (ObjectUtil.isEmpty(receiveRecordInformations)){
            return ResponseRule.no("没有找到记录");
        }

        //收货总数
        Integer totalReceiveCount = 0;
        //使用时间总数
        int totalUseTime=0;

        //获取所有已完成收货单
        for (ReceiveRecordInformation receiveRecordInformation : receiveRecordInformations) {
            System.out.println(totalUseTime);
            System.out.println(totalReceiveCount);
            //计算所有已用时间
            totalUseTime+=Integer.parseInt(receiveRecordInformation.getUseTime());
            //计算所有收货数
            totalReceiveCount+= receiveRecordInformation.getReceiveCount();
        }


        //收获书
        result.put("receiveCount",totalReceiveCount<=0?0:totalReceiveCount);

        //平均收获
        result.put("aveReceive",totalReceiveCount<=0?0:totalUseTime/totalReceiveCount);

        result.put("aveReceiveOfDay",totalReceiveCount<=0?0:totalReceiveCount/Integer.parseInt(DateUtil.endOfMonth(DateTime.now()).toString("dd")));
        result.put("aveOrdersOfDay",reservationStartCarInformations.size()/Integer.parseInt(DateUtil.endOfMonth(DateTime.now()).toString("dd"))<=1?1:reservationStartCarInformations.size()/Integer.parseInt(DateUtil.endOfMonth(DateTime.now()).toString("dd")));
        return ResponseRule.ok(result);
    }

    @Override
    public ResponseRule findStartCarByReceiver(String receiverNumber) {
        List<ReservationStartCarInformation> listByActualReceiverNumber = startCarMapper.getListByActualReceiverNumber(receiverNumber);
        return ResponseRule.ok(listByActualReceiverNumber);
    }

    @Override
    public ResponseRule receiverHoliday(String receiverNumber) {
        ReceiverInformation receiverByReceiverNumber = getReceiverByReceiverNumber(receiverNumber);
        receiverByReceiverNumber.setDutyFlag(1);
        this.addAndUp(receiverByReceiverNumber);
        return ResponseRule.ok("修改假期状态成功");
    }

    @Override
    public ResponseRule receiverWork(String receiverNumber) {
        ReceiverInformation receiverByReceiverNumber = getReceiverByReceiverNumber(receiverNumber);
        receiverByReceiverNumber.setDutyFlag(0);
        this.addAndUp(receiverByReceiverNumber);
        return ResponseRule.ok("修改工作状态成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseRule getInspectItem(String reservationNumber) {
        ReservationInformation reser = reservationService.getByReservationNumber(reservationNumber);
        //找到订单里面所有的预检类
        LambdaQueryWrapper<ReservationToInspect> eq = rtiService.getWrapper().eq(ReservationToInspect::getReservationNumber, reser.getReservationNumber());
        List<ReservationToInspect> reservationToInspects = rtiService.selectList(eq);
        List inspects = new ArrayList();
        //循环预检类
        for (ReservationToInspect reservationToInspect : reservationToInspects) {
            InspectType inspectType = inspectTypeMapper.selectById(reservationToInspect.getInspectTypeNumber());
            //预检集合List
            LambdaQueryWrapper<InspectName> eq1 = inspectNameMapper.getWrapper().eq(InspectName::getInspectTypeNumber, inspectType.getId());
            List<InspectName> inspectNames = inspectNameMapper.selectList(eq1);
            //防止循环引用
//            List<InspectName> clone = ObjectUtil.cloneByStream(inspectNames);
            //放入MAP
            Map<String, Object> inspect = new HashMap<>();
            inspect.put("item", inspectType.getInspectTypeName());
            inspect.put("items", inspectNames);
            inspects.add(inspect);
        }
        if (inspects.size() == 0)
            return ResponseRule.no("没有预检项");
        String s = JSONObject.toJSONString(inspects, SerializerFeature.DisableCircularReferenceDetect);
        JSONArray objects = JSONObject.parseArray(s);
        return ResponseRule.ok(objects);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseRule inspectSuccess(String reservationNumber, String receiverNumber, Integer inspectNumber) {
        InspectRecord inspectRecord = new InspectRecord();
        inspectRecord.setInspectId(inspectNumber);
        inspectRecord.setInspectSuccess(1);
        inspectRecord.setReceiverNumber(receiverNumber);
        inspectRecord.setReservationNumber(reservationNumber);
        inspectRecordMapper.save(inspectRecord);
        return ResponseRule.ok("成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseRule delInspect(String reservationNumber, String receiverNumber, Integer inspectNumber) {
        //获取这个订单的所有检查规则
        LambdaQueryWrapper<InspectRecord> eq = inspectRecordMapper.getWrapper().eq(InspectRecord::getReservationNumber, reservationNumber).
                eq(InspectRecord::getReceiverNumber, receiverNumber);
        List<InspectRecord> inspectRecords = inspectRecordMapper.selectList(eq);
        if (inspectRecords.size() == 0) {
            return ResponseRule.no();
        }
        //循环规则找到某一条规则删除
        for (InspectRecord inspectRecord : inspectRecords) {
            if (Objects.equals(inspectRecord.getInspectId(), inspectNumber)) {
                inspectRecordMapper.deleteById(inspectRecord.getId());
                return ResponseRule.ok();
            }
        }
        return ResponseRule.no();
    }

    @Override
    public ResponseRule getAllInspectByReservation(String reservationNumber, String receiverNumber) {
        //获取这个订单的所有检查规则
        LambdaQueryWrapper<InspectRecord> eq = inspectRecordMapper.getWrapper().eq(InspectRecord::getReservationNumber, reservationNumber).
                eq(InspectRecord::getReceiverNumber, receiverNumber);
        List<InspectRecord> inspectRecords = inspectRecordMapper.selectList(eq);
        if (inspectRecords.size() == 0)
            ResponseRule.no();
        return ResponseRule.ok(inspectRecords);
    }
}
